import { useState, useCallback } from 'react';

export interface ApiType {
  (this: any, ...args: any[]): Promise<any>;
  [k: string]: any;
}

export enum ApiState {
  UNRESOLVED,
  LOADING,
  FAIL,
  SUCCESS,
}

export interface UseApiLoadingReturnValueType {
  apiState: ApiState;
  apiLoading: boolean;
  api: ApiType;
}

export default function useApiLoading(
  api: ApiType
): UseApiLoadingReturnValueType {
  const [apiState, setApiState] = useState(ApiState.UNRESOLVED);
  const wrappedApi: ApiType = useCallback(
    function (this: any, ...args: any[]) {
      const self = this;
      setApiState(ApiState.LOADING);
      return new Promise((resolve, reject) => {
        api
          .apply(self, args)
          .then((result) => {
            setApiState(ApiState.SUCCESS);
            resolve(result);
          })
          .catch((err) => {
            setApiState(ApiState.FAIL);
            reject(err);
          });
      });
    },
    [api]
  );
  const apiLoading = apiState === ApiState.LOADING;
  return {
    api: wrappedApi,
    apiLoading,
    apiState,
  };
}
